<?php
/**
 * 
 * @todo description of this class
 * 
 * @author Alton Crossley <crossleyframework@nogahidebootstrap.com>
 * @package Crossley Framework
 *  
 * @copyright Copyright (c) 2003-2009, Nogaide BootStrap INC. All rights reserved.
 * @license BSD http://opensource.org/licenses/bsd-license.php
 * @version $Id:$
 * 
 */
class X_Data_Meta_Query
{
    const SELECT = 'SELECT';
    const UPDATE = 'UPDATE';
    const DELETE = 'DELETE';
    /**
     * array of table objects for validating and updating query
     *
     * @var array of X_Data_Meta_Table
     */
    public $aTables = array();
    /**
     * array of column names keyed by table names
     *
     * @var array of string
     */
    public $aColumnNames = array();
    /**
     * where filter strings
     * 
     * @var array
     */
    protected $_aWhereFilters = array();
    /**
     * string matching X_Data_Meta_Query contstants
     * 
     * @var unknown_type
     */
    protected $_mode = 'select';
    /**
     * hashtable mapping table anames to their abbreviation
     * 
     * @var array
     */
    protected $_aTableAbbr = array();
	/**
     * add a column to be acted upon
     * (chainable)
     *
     * @param string|array $sColumnName
     * @param string $sTableName
     * @return X_Data_Meta_Query_Mysql
     */
    public function addSelect($xColumns, $sTableName)
    {
        if (empty($xColumns) || empty($sTableName) && empty($this->aTables))
        {
            return $this;
        }
        
        if (!empty($sTableName))
        {
        	$sKey = $this->_registerTable($sTableName);        	
        }
        
        $this->addColumn($sKey, $xColumns);
        
        return $this;
    }
    /**
     * add columns
     * (chainable)
     * 
     * @param $sTableKey
     * @param $xColumns string|array
     */
    public function addColumn($sTableKey, $xColumns)
    {
    	if (is_array($xColumns) && array_key_exists($sTableKey, $this->aColumnNames) && is_array($this->aColumnNames[$sTableKey]))
    	{
    		$this->aColumnNames[$sTableKey] = array_merge($this->aColumnNames[$sTableKey], $xColumns);   
		}
        else if (is_array($xColumns))
        {
        	$this->aColumnNames[$sTableKey] = $xColumns;
        }
        else
        {
            $this->aColumnNames[$sTableKey][] = (string)$xColumns;
        }
        
        return $this;
    }
    /**
     * register a table abbreviation if possible
     * 
     * @param string $sTableName
     */
    protected function _registerTable($sTableName)
    {
        $sTableName = (string)$sTableName;
        if (array_key_exists($sTableName, $this->_aTableAbbr)) return $this->_aTableAbbr[$sTableName];
        
        // start abbreviation length
        $iLength = 1;
        $sTAbbr = substr($sTableName, 0, $iLength);
        while (array_search($sTAbbr, $this->_aTableAbbr) && $iLength <= strlen($sTableName))
        {
            $iLength = 1;
            $sTAbbr = substr($sTableName, 0, $iLength);
        }
        $this->_aTableAbbr[$sTableName] = $sTAbbr;
        return (string)$sTAbbr;
    } 
    
    public function Where($sString)
    {
        $this->_aWhereFilters[] = $sString;
        return $this;
    }
	/**
     * alter query mode
     * 
     * @param unknown_type $MODE
     */
    public function setMode($MODE)
    {
        $this->_mode = (string)$MODE;
        return $this;
    }
    /**
     * add a table to be acted upon
     * (chainable)
     *
     * @param X_Data_Meta_Table $oTable
     * @return X_Data_Meta_Query_Mysql 
     */
    public function addTable(X_Data_Meta_Table $oTable)
    {
        $this->aTables[$oTable->getName()] = $oTable;
        $sKey = $this->_registerTable($oTable->sName);
        $this->addColumn($sKey, $oTable->getColumnNames());
        return $this;
    }

    public function getQuery()
    {
        $sQuery = $this->_mode;
        
        // Columns
        $sPrefix = null;
        foreach ($this->aColumnNames as $sTable => $xColumn) {
        	if (is_array($xColumn))
        	{
        		$sCollumnsQuery = null;
        	    foreach ($xColumn as $sColumnName)
        	    {
        	    	if (strlen($sCollumnsQuery)) $sCollumnsQuery .= ', ';
        	        $sCollumnsQuery .= $sPrefix . " " . $sTable . "." . $sColumnName;
        	    }
        	    
        	    $sQuery .= $sCollumnsQuery;
        	}
        	else
        	{
        	    $sQuery .= $sPrefix . " " . $sTable . "." . $xColumn;
        	}
        	$sPrefix = ",";
        }
        
        // Table Joins
        $bJoin = false;
        foreach ($this->_aTableAbbr as $sTable => $sAbbr) {
        	if ($bJoin)
        	{
        	    $sQuery .= " join " . $sTable . 
        	    	" " . $sAbbr . 
        	    	" " .$this->_getJoinRule($sTable);
        	}
        	else
        	{
        	    $sQuery .= " FROM " . $sTable . " " . $sAbbr;
        	}
        	$bJoin = true;
        }
        
        // Get Where
        $bWhere = false;
        foreach ($this->_aWhereFilters as $sWhereFiilter)
        {
            if ($bWhere)
            {
                $sQuery .= " AND " . $sWhereFiilter;
            }
            else
            {
                $sQuery .= " WHERE " . $sWhereFiilter;
            }
            $bWhere = true;
        }
        
        return $sQuery;
    }
    
    protected function _getJoinRule($sTableName)
    {
        return "";
    }
    
}